home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr47 / 335_04.zip / FRAOSUB.C < prev    next >
C/C++ Source or Header  |  1993-04-13  |  15KB  |  793 lines

  1. /*
  2. HEADER:     ;
  3. TITLE:         Frankenstein Cross Assemblers;
  4. VERSION:     2.0;
  5. DESCRIPTION: "    Reconfigurable Cross-assembler producing Intel (TM)
  6.         Hex format object records.  ";
  7. SYSTEM:     UNIX, MS-Dos ;
  8. FILENAME:     fraosub.c;
  9. WARNINGS:     "This software is in the public domain.  
  10.         Any prior copyright claims are relinquished.  
  11.  
  12.         This software is distributed with no warranty whatever.  
  13.         The author takes no responsibility for the consequences 
  14.         of its use."  ;
  15. SEE-ALSO:     frasmain.c;
  16. AUTHORS:     Mark Zenier;
  17. */
  18.  
  19. /*
  20.     description    output pass utility routines
  21.     history        September 27, 1987
  22.             March 15, 1988   release 1.1 WIDTH
  23.             September 14, 1990  Dosify, 6 char unique names
  24. */
  25.  
  26.  
  27. #include <stdio.h>
  28. #include "frasmdat.h"
  29. #include "fragcon.h"
  30.  
  31. #define OUTRESULTLEN 256
  32. #define NUMHEXPERL 16
  33. #define SOURCEOFFSET 24
  34. #define NUMHEXSOURCE 6
  35.  
  36. int linenumber = 0;
  37. char lineLbuff[INBUFFSZ];
  38. int lineLflag = FALSE;
  39.  
  40. static unsigned char    outresult[OUTRESULTLEN];
  41. static int    nextresult;
  42. static long     genlocctr, resultloc;
  43.  
  44. static char    *oeptr;
  45.  
  46. #define    MAXIMPWID    24
  47.  
  48. static long widthmask[MAXIMPWID+1] =
  49. {
  50. /* 0 */        1L,
  51. /* 1 */        1L,
  52. /* 2 */        (1L <<  2 ) -1,
  53. /* 3 */        (1L <<  3 ) -1,
  54. /* 4 */        (1L <<  4 ) -1,
  55. /* 5 */        (1L <<  5 ) -1,
  56. /* 6 */        (1L <<  6 ) -1,
  57. /* 7 */        (1L <<  7 ) -1,
  58. /* 8 */        (1L <<  8 ) -1,
  59. /* 9 */        (1L <<  9 ) -1,
  60. /* 10 */    (1L <<  10 ) -1,
  61. /* 11 */    (1L <<  11 ) -1,
  62. /* 12 */    (1L <<  12 ) -1,
  63. /* 13 */    (1L <<  13 ) -1,
  64. /* 14 */    (1L <<  14 ) -1,
  65. /* 15 */    (1L <<  15 ) -1,
  66. /* 16 */    (1L <<  16 ) -1,
  67. /* 17 */    (1L <<  17 ) -1,
  68. /* 18 */    (1L <<  18 ) -1,
  69. /* 19 */    (1L <<  19 ) -1,
  70. /* 20 */    (1L <<  20 ) -1,
  71. /* 21 */    (1L <<  21 ) -1,
  72. /* 22 */    (1L <<  22 ) -1,
  73. /* 23 */    (1L <<  23 ) -1,
  74. /* 24 */    (1L <<  24 ) -1
  75. };
  76.     
  77.  
  78. static long dgethex()
  79. /*
  80.     description    convert the character string pointed to by
  81.             the output expression pointer to a long integer
  82.     globals        oeptr, the output expression pointer
  83.     return        the value
  84. */
  85. {
  86.     long rv = 0;
  87.  
  88.     while( *oeptr != '\0')
  89.     {
  90.         switch(*oeptr)
  91.         {
  92.         case '0':
  93.         case '1':
  94.         case '2':
  95.         case '3':
  96.         case '4':
  97.         case '5':
  98.         case '6':
  99.         case '7':
  100.         case '8':
  101.         case '9':
  102.             rv = (rv << 4) + ((*oeptr) - '0');
  103.             break;
  104.  
  105.         case 'a':
  106.         case 'b':
  107.         case 'c':
  108.         case 'd':
  109.         case 'e':
  110.         case 'f':
  111.             rv = (rv << 4) + ((*oeptr) - 'a' + 10);
  112.             break;
  113.         
  114.         case 'A':
  115.         case 'B':
  116.         case 'C':
  117.         case 'D':
  118.         case 'E':
  119.         case 'F':
  120.             rv = (rv << 4) + ((*oeptr) - 'A' + 10);
  121.             break;
  122.  
  123.         default:
  124.             return rv;
  125.         }
  126.  
  127.         oeptr++;
  128.     }
  129.  
  130.     return rv;
  131. }
  132.     
  133.  
  134. outphase()
  135. /*
  136.     description    process all the lines in the intermediate file
  137.     globals        the input line
  138.             the output expression pointer
  139.             line number
  140.             file name
  141.             the binary output array and counts
  142. */
  143. {
  144.     int firstchar;
  145.  
  146.     for(;;)
  147.     {
  148.         if((firstchar = fgetc(intermedf)) == EOF)
  149.             break;
  150.  
  151.         if(firstchar == 'L')
  152.         {
  153.             if(listflag)
  154.                 flushlisthex();
  155.  
  156.             if( fgets(&lineLbuff[1], INBUFFSZ-1, intermedf) 
  157.              == (char *)NULL)
  158.             {
  159.         frp2error( "error or premature end of intermediate file");
  160.                 break;
  161.             }
  162.  
  163.             lineLflag = TRUE;
  164.         }
  165.         else
  166.         {
  167.             finbuff[0] = firstchar;
  168.             if(fgets( &finbuff[1], INBUFFSZ-1, intermedf) 
  169.              == (char *)NULL)
  170.             {
  171.         frp2error("error or premature end of intermediate file");
  172.                 break;
  173.             }
  174.         }
  175.     
  176.         switch(firstchar)
  177.         {
  178.         case 'E': /* error */
  179.             if(listflag)
  180.             {
  181.                 flushsourceline();
  182.                 fputs(&finbuff[2], loutf);
  183.             }
  184.             else
  185.             {
  186.                 fprintf(loutf, "%s - line %d - %s", 
  187.                     currentfnm, linenumber, &finbuff[2]);
  188.             }
  189.             break;
  190.  
  191.         case 'L': /* listing */
  192.             linenumber++;
  193.             break;
  194.  
  195.         case 'C': /* comment / uncounted listing */
  196.             if(listflag)
  197.             {
  198.                 char *stuff = strchr(finbuff, '\n');
  199.  
  200.                 if(stuff != NULL)
  201.                     *stuff = '\0';
  202.  
  203.                 fprintf(loutf,"%-*.*s", 
  204.                  SOURCEOFFSET, SOURCEOFFSET, &finbuff[2]);
  205.                 if(lineLflag)
  206.                 {
  207.                     fputs(&lineLbuff[2], loutf);
  208.                     lineLflag = FALSE;
  209.                 }
  210.                 else
  211.                 {
  212.                     fputc('\n', loutf);
  213.                 }
  214.             }
  215.             break;
  216.  
  217.         case 'P': /* location set */
  218.             oeptr = &finbuff[2];
  219.             currseg = dgethex();
  220.             oeptr++;
  221.             genlocctr = locctr = dgethex();
  222.             break;
  223.         
  224.         case 'D': /* data */
  225.             oeptr = &finbuff[2];
  226.             nextresult = 0;
  227.             resultloc = genlocctr;
  228.             outeval();
  229.             if(hexflag)
  230.                 outhexblock();
  231.             if(listflag)
  232.                 listhex();
  233.             break;
  234.         
  235.         case 'F': /* file start */
  236.             {
  237.                 char *tp;
  238.                 if( (tp = strchr(finbuff,'\n')) != (char *)NULL)
  239.                     *tp = '\0';
  240.                 strncpy(currentfnm, &finbuff[2], 100);
  241.                 currentfnm[99] = '\0';
  242.             }
  243.             lnumstk[currfstk++] = linenumber;
  244.             linenumber = 0;
  245.             break;
  246.         
  247.         case 'X': /* file resume */
  248.             {
  249.                 char *tp;
  250.                 if( (tp = strchr(finbuff,'\n')) != (char *)NULL)
  251.                     *tp = '\0';
  252.                 strncpy(currentfnm, &finbuff[2], 100);
  253.                 currentfnm[99] = '\0';
  254.             }
  255.             linenumber = lnumstk[--currfstk];
  256.             break;
  257.  
  258.         default:
  259.             frp2error("unknown intermediate file command");
  260.             break;
  261.         }
  262.     }
  263.  
  264.     if(hexflag)
  265.         flushhex();
  266.  
  267.     if(listflag)
  268.         flushlisthex();
  269. }
  270.  
  271. outeval()
  272. /*
  273.     description    convert the polish form character string in the 
  274.             intermediate file 'D' line to binary values in the
  275.             output result array.
  276.     globals        the output expression pointer
  277.             the output result array
  278. */
  279. {
  280.     register long etop = 0;
  281.  
  282.     register struct evstkel *estkm1p = &estk[0];
  283.  
  284.     while( *oeptr != '\0')
  285.     {
  286.         switch(*oeptr)
  287.         {
  288.         case '0':
  289.         case '1':
  290.         case '2':
  291.         case '3':
  292.         case '4':
  293.         case '5':
  294.         case '6':
  295.         case '7':
  296.         case '8':
  297.         case '9':
  298.             etop = (etop << 4) + ((*oeptr) - '0');
  299.             break;
  300.  
  301.         case 'a':
  302.         case 'b':
  303.         case 'c':
  304.         case 'd':
  305.         case 'e':
  306.         case 'f':
  307.             etop = (etop << 4) + ((*oeptr) - 'a' + 10);
  308.             break;
  309.         
  310.         case 'A':
  311.         case 'B':
  312.         case 'C':
  313.         case 'D':
  314.         case 'E':
  315.         case 'F':
  316.             etop = (etop << 4) + ((*oeptr) - 'A' + 10);
  317.             break;
  318.  
  319. #include "fraeuni.h"
  320. #include "fraebin.h"
  321.         case IFC_SYMB:
  322.             {
  323.                 struct symel *tsy;
  324.  
  325.                 tsy = symbindex[etop];
  326.                 if(tsy -> seg <= 0)
  327.                 {
  328.                     frp2undef(tsy);
  329.                     etop = 0;
  330.                 }
  331.                 else
  332.                 {
  333.                     if(tsy -> seg == SSG_EQU ||
  334.                        tsy -> seg == SSG_SET)
  335.                     {
  336.             frp2warn( "forward reference to SET/EQU symbol");
  337.                     }
  338.                     etop = tsy -> value;
  339.                 }
  340.             }
  341.             break;
  342.  
  343.         case IFC_CURRLOC: 
  344.             etop = genlocctr;
  345.             break;
  346.  
  347.         case IFC_PROGCTR:
  348.             etop = locctr;
  349.             break;
  350.  
  351.         case IFC_DUP:
  352.             if(estkm1p >= &estk[PESTKDEPTH-1])
  353.             {
  354.                 frp2error("expression stack overflow");
  355.             }
  356.             else
  357.             {
  358.                 (++estkm1p)->v = etop;
  359.             }
  360.             break;
  361.  
  362.         case IFC_LOAD:
  363.             if(estkm1p >= &estk[PESTKDEPTH-1])
  364.             {
  365.                 frp2error("expression stack overflow");
  366.             }
  367.             else
  368.             {
  369.                 (++estkm1p)->v = etop;
  370.             }
  371.             etop = 0;
  372.             break;
  373.  
  374.         case IFC_CLR:
  375.             etop = 0;
  376.             break;
  377.  
  378.         case IFC_CLRALL:
  379.             etop = 0;
  380.             estkm1p = &estk[0];
  381.             break;
  382.  
  383.         case IFC_POP:
  384.             etop = (estkm1p--)->v;
  385.             break;
  386.  
  387.         case IFC_TESTERR:
  388.             if(etop)
  389.             {
  390.                 frp2error(
  391.             "expression fails validity test");
  392.             }
  393.             break;
  394.  
  395.         case IFC_SWIDTH:
  396.             if( etop > 0 && etop <= MAXIMPWID)
  397.             {
  398.                 if( estkm1p->v < -(widthmask[etop-1]+1) ||
  399.                     estkm1p->v > widthmask[etop-1] )
  400.                 {
  401.                     frp2error(
  402.                 "expression exceeds available field width");
  403.                 }
  404.                 etop = ((estkm1p--)->v)  & widthmask[etop];
  405.             }
  406.             else
  407.                 frp2error("unimplemented width");
  408.             break;
  409.  
  410.         case IFC_WIDTH:
  411.             if( etop > 0 && etop <= MAXIMPWID)
  412.             {
  413.                 if( estkm1p->v < -(widthmask[etop-1]+1) ||
  414.                     estkm1p->v > widthmask[etop] )
  415.                 {
  416.                     frp2error(
  417.                 "expression exceeds available field width");
  418.                 }
  419.                 etop = ((estkm1p--)->v)  & widthmask[etop];
  420.             }
  421.             else
  422.                 frp2error("unimplemented width");
  423.             break;
  424.  
  425.         case IFC_IWIDTH:
  426.             if( etop > 0 && etop <= MAXIMPWID)
  427.             {
  428.                 if( estkm1p->v < 0 ||
  429.                     estkm1p->v > widthmask[etop] )
  430.                 {
  431.                     frp2error(
  432.                 "expression exceeds available field width");
  433.                 }
  434.                 etop = ((estkm1p--)->v)  & widthmask[etop];
  435.             }
  436.             else
  437.                 frp2error("unimplemented width");
  438.             break;
  439.  
  440.         case IFC_EMU8:
  441.             if( etop >= -128 && etop <= 255)
  442.             {
  443.                 outresult[nextresult++] = etop & 0xff;
  444.             }
  445.             else
  446.             {
  447.                 outresult[nextresult++] = 0;
  448.                 frp2error(
  449.             "expression exceeds available field width");
  450.             }
  451.             genlocctr ++;
  452.             etop = 0;
  453.             break;
  454.  
  455.         case IFC_EMS7:
  456.             if(etop >= -128 && etop <= 127)
  457.             {
  458.                 outresult[nextresult++] = etop & 0xff;
  459.             }
  460.             else
  461.             {
  462.                 outresult[nextresult++] = 0;
  463.                 frp2error(
  464.             "expression exceeds available field width");
  465.             }
  466.             genlocctr ++;
  467.             etop = 0;
  468.             break;
  469.  
  470.         case IFC_EM16:
  471.             if(etop >= -32768L && etop <= 65535L)
  472.             {
  473.                 outresult[nextresult++] = (etop >> 8) & 0xff;
  474.                 outresult[nextresult++] = etop & 0xff;
  475.             }
  476.             else
  477.             {
  478.                 outresult[nextresult++] = 0;
  479.                 outresult[nextresult++] = 0;
  480.                 frp2error(
  481.             "expression exceeds available field width");
  482.             }
  483.             genlocctr += 2;
  484.             etop = 0;
  485.             break;
  486.  
  487.         case IFC_EMBR16:
  488.             if(etop >= -32768L && etop <= 65535L)
  489.             {
  490.                 outresult[nextresult++] = etop & 0xff;
  491.                 outresult[nextresult++] = (etop >> 8) & 0xff;
  492.             }
  493.             else
  494.             {
  495.                 outresult[nextresult++] = 0;
  496.                 outresult[nextresult++] = 0;
  497.                 frp2error(
  498.             "expression exceeds available field width");
  499.             }
  500.             genlocctr += 2;
  501.             etop = 0;
  502.             break;
  503.  
  504.         default:
  505.             break;
  506.         }
  507.         oeptr++;
  508.     }
  509. }
  510.  
  511. static long lhaddr, lhnextaddr;
  512. static int lhnew, lhnext = 0;
  513. static unsigned char listbuffhex[NUMHEXPERL];
  514.  
  515. flushlisthex()
  516. /*
  517.     description    output the residue of the hexidecimal values for
  518.             the previous assembler statement.
  519.     globals        the new hex list flag
  520. */
  521. {
  522.     listouthex();
  523.     lhnew = TRUE;
  524. }
  525.  
  526. listhex()
  527. /*
  528.     description    buffer the output result to block the hexidecimal 
  529.             listing on the output file to NUMHEXPERL bytes per
  530.             listing line.
  531.     globals        The output result array and count
  532.             the hex line buffer and counts
  533. */
  534. {
  535.     register int cht;
  536.     register long inhaddr = resultloc;
  537.  
  538.     if(lhnew)
  539.     {
  540.         lhaddr = lhnextaddr = resultloc;
  541.         lhnew = FALSE;
  542.     }
  543.  
  544.     for(cht = 0; cht < nextresult; cht++)
  545.     {
  546.         if(lhnextaddr != inhaddr 
  547.          || lhnext >= (lineLflag ? NUMHEXSOURCE : NUMHEXPERL ) )
  548.         {
  549.             listouthex();
  550.             lhaddr = lhnextaddr = inhaddr;
  551.         }
  552.         listbuffhex[lhnext++] = outresult[cht];
  553.         lhnextaddr ++;
  554.         inhaddr ++;
  555.     }
  556. }
  557.  
  558. listouthex()
  559. /*
  560.     description    print a line of hexidecimal on the listing
  561.     globals        the hex listing buffer
  562. */
  563. {
  564.     register int cn;
  565.     register int tc;
  566.  
  567.     if(lhnext > 0)
  568.     {
  569.         fputc(hexch((int)lhaddr>>12), loutf);
  570.         fputc(hexch((int)lhaddr>>8), loutf);
  571.         fputc(hexch((int)lhaddr>>4), loutf);
  572.         fputc(hexch((int)lhaddr), loutf);
  573.         fputc(' ', loutf);
  574.  
  575.         for(cn = 0; cn < lhnext; cn++)
  576.         {
  577.             fputc(hexch((int)(tc = listbuffhex[cn])>>4), loutf);
  578.             fputc(hexch(tc), loutf);
  579.             fputc(' ', loutf);
  580.         }
  581.  
  582.         if( ! lineLflag)
  583.             fputc('\n', loutf);
  584.     }
  585.  
  586.     if(lineLflag)
  587.     {
  588.         if(lineLbuff[2] != '\n')
  589.         {
  590.             switch(lhnext)
  591.             {
  592.             case 0:
  593.                 fputs("\t\t\t",loutf);
  594.                 break;
  595.             case 1:
  596.             case 2:
  597.             case 3:
  598.                 fputs("\t\t",loutf);
  599.                 break;
  600.             case 4:
  601.             case 5:
  602.             case 6:
  603.                 fputs("\t",loutf);
  604.             default:
  605.                 break;
  606.             }
  607.  
  608.             fputs(&lineLbuff[2], loutf);
  609.             lineLflag = FALSE;
  610.         }
  611.         else
  612.         {
  613.             fputc('\n', loutf);
  614.         }
  615.     }
  616.         
  617.     lhnext = 0;
  618. }
  619.  
  620. #define INTELLEN 32
  621.  
  622. static long nextoutaddr, blockaddr;
  623. static int hnextsub;
  624. static char hlinebuff[INTELLEN];
  625.  
  626.  
  627. outhexblock()
  628. /*
  629.     description    buffer the output result to group adjacent output
  630.             data into longer lines.
  631.     globals        the output result array
  632.             the intel hex line buffer
  633. */
  634. {
  635.     long inbuffaddr = resultloc;
  636.     static int first = TRUE;
  637.  
  638.     int loopc;
  639.  
  640.     if(first)
  641.     {
  642.         nextoutaddr = blockaddr = resultloc;
  643.         hnextsub = 0;
  644.         first = FALSE;
  645.     }
  646.  
  647.     for(loopc = 0; loopc < nextresult; loopc++)
  648.     {
  649.         if(nextoutaddr != inbuffaddr || hnextsub >= INTELLEN)
  650.         {
  651.             intelout(0, blockaddr, hnextsub, hlinebuff);
  652.             blockaddr = nextoutaddr = inbuffaddr;
  653.             hnextsub = 0;
  654.         }
  655.         hlinebuff[hnextsub++] = outresult[loopc];
  656.         nextoutaddr++;
  657.         inbuffaddr++;
  658.     }
  659. }
  660.  
  661. flushhex()
  662. /*
  663.     description    flush the intel hex line buffer at the end of
  664.             the second pass
  665.     globals        the intel hex line buffer
  666. */
  667. {
  668.     if(hnextsub > 0)
  669.         intelout(0, blockaddr, hnextsub, hlinebuff);
  670.     if(endsymbol != SYMNULL && endsymbol -> seg > 0)
  671.         intelout(1, endsymbol -> value, 0, "");
  672.     else
  673.         intelout(1, 0L, 0, "");
  674.         
  675. }
  676.  
  677.  
  678. intelout(type, addr, count, data)
  679.     int type;
  680.     long addr;
  681.     int count;
  682.     char data[];
  683. /*
  684.     description    print a line of intel format hex data to the output
  685.             file
  686.     parameters    see manual for record description
  687. */
  688. {
  689.     register int temp, checksum;
  690.  
  691.     fputc(':', hexoutf);
  692.     fputc(hexch(count>>4),hexoutf);
  693.     fputc(hexch(count),hexoutf);
  694.     fputc(hexch((int)addr>>12),hexoutf);
  695.     fputc(hexch((int)addr>>8),hexoutf);
  696.     fputc(hexch((int)addr>>4),hexoutf);
  697.     fputc(hexch((int)addr),hexoutf);
  698.     fputc(hexch(type>>4),hexoutf);
  699.     fputc(hexch(type),hexoutf);
  700.  
  701.     checksum = ((addr >> 8) & 0xff) + (addr & 0xff) + (count & 0xff);
  702.     checksum += type & 0xff;
  703.  
  704.     for(temp = 0; temp < count; temp ++)
  705.     {
  706.         checksum += data[temp] & 0xff;
  707.         fputc(hexch(data[temp] >> 4), hexoutf);
  708.         fputc(hexch(data[temp]), hexoutf);
  709.     }
  710.  
  711.     checksum = (-checksum) & 0xff;
  712.     fputc(hexch(checksum>>4), hexoutf);
  713.     fputc(hexch(checksum), hexoutf);
  714.     fputc('\n',hexoutf);
  715. }
  716.  
  717.  
  718. frp2undef(symp)
  719.     struct symel * symp;
  720. /*
  721.     description    second pass - print undefined symbol error message on
  722.             the output listing device.  If the the listing flag
  723.             is false, the output device is the standard output, and
  724.             the message format is different.
  725.     parameters    a pointer to a symbol table element
  726.     globals        the count of errors
  727. */
  728. {
  729.     if(listflag)
  730.     {
  731.         flushsourceline();
  732.         fprintf(loutf," ERROR -  undefined symbol %s\n", symp ->symstr);
  733.     }
  734.     else
  735.         fprintf(loutf, "%s - line %d - ERROR - undefined symbol  %s\n", 
  736.             currentfnm, linenumber, symp -> symstr);
  737.     errorcnt++;
  738. }
  739.  
  740. frp2warn(str)
  741.     char * str;
  742. /*
  743.     description    second pass - print a warning message on the listing
  744.             file, varying the format for console messages.
  745.     parameters    the message
  746.     globals        the count of warnings
  747. */
  748. {
  749.     if(listflag)
  750.     {
  751.         flushsourceline();
  752.         fprintf(loutf, " WARNING - %s\n", str);
  753.     }
  754.     else
  755.         fprintf(loutf, "%s - line %d - WARNING - %s\n", 
  756.             currentfnm, linenumber, str);
  757.     warncnt++;
  758. }
  759.  
  760.  
  761. frp2error(str)
  762.     char * str;
  763. /*
  764.     description    second pass - print a message on the listing file
  765.     parameters    message
  766.     globals        count of errors
  767. */
  768. {
  769.     if(listflag)
  770.     {
  771.         flushsourceline();
  772.         fprintf(loutf, " ERROR - %s\n", str);
  773.     }
  774.     else
  775.         fprintf(loutf, "%s - line %d - ERROR - %s\n", 
  776.             currentfnm, linenumber, str);
  777.     errorcnt++;
  778. }
  779.  
  780. flushsourceline()
  781. /*
  782.     description    flush listing line buffer before an error for
  783.             that line is printed
  784. */
  785. {
  786.     if(listflag && lineLflag)
  787.     {
  788.         fputs("\t\t\t", loutf);
  789.         fputs(&lineLbuff[2], loutf);
  790.         lineLflag = FALSE;
  791.     }
  792. }
  793.